import config from '@/config/index';
import path from 'path';
import { Sequelize, Options } from 'sequelize';
import fs from 'fs';
import { IModelGroup, TModels } from './types';

const { USER, PASSWORD, PORT, DB, HOST } = config.MYSQL_CONFIG;

class ClassSequelize {
  constructor() {
    this.sequelizeManager = new Sequelize(
      DB,
      USER,
      PASSWORD,
      this.MYSQL_OPTION,
    );
  }

  public readonly sequelizeManager: Sequelize;

  public readonly models: IModelGroup = {};

  private readonly MYSQL_OPTION: Options = {
    dialect: 'mysql',
    host: HOST,
    port: PORT,
    // models: [path.resolve(__dirname, '../models')],
    pool: {
      max: 1,
      min: 1,
      acquire: 30000,
      idle: 10000,
    },
    define: {
      underscored: false,
      charset: 'utf8mb4',
      collate: 'utf8mb4_general_ci',
      freezeTableName: true,
      timestamps: true,
      paranoid: true,
    },
    logging: false,
  };

  /**
   * sequelize连接验证
   */
  public async connect(): Promise<void> {
    return this.sequelizeManager
      .authenticate()
      .then(() => {
        console.info('new mysql connect success!');
      })
      .catch((error: Error) => {
        console.error('new cannot connect mysql: ', error.message);
      });
  }

  /**
   * 这叫同步？
   */
  public syncModels() {
    const isProd = process.env.NODE_ENV === 'production';
    if (!isProd) {
      this.sequelizeManager.sync({ force: true, alter: true }).then(
        () => {
          console.info('new Sync models sucessful!');
        },
        (err) => {
          console.error('new Sync models failed: ', err.message);
        },
      );
    }
  }

  public registerModels() {
    const modelDir = path.resolve(__dirname, '../models');
    const dirs: any = fs.readdirSync(modelDir);
    for (let key in dirs) {
      const name: string = dirs[key].replace(/.[j|t]s$/, '');
      if (name === 'index') {
        continue;
      }
      const filepath = path.resolve(modelDir, dirs[key]);
      const file = require(filepath);
      const MODELS = file['Models'];
      const OPTIONS = file['Options'];
      // console.log(name, MODELS, OPTIONS);
      const res = this.sequelizeManager.define(name, MODELS, OPTIONS);
      this.models[name] = res;
    }
  }

  getModels() {
    return this.models as TModels;
  }
}

export const sequelize = new ClassSequelize();

export const sequelizeManager = sequelize.sequelizeManager;

sequelize.connect();

sequelize.registerModels();

// sequelize.syncModels();

export const models = sequelize.getModels();

export default ClassSequelize;
